package unit;

import hospital.*;

import java.util.ArrayList;

import movement.Location;

import dispatch.*;

/**
 * A class for to create a Garage
 * 
 */
public class Garage {

	/**
	 * Variable registering this garage his units (ready for assignment)
	 */
	private ArrayList<Unit> units;

	/**
	 * Variable registering the hospitalboard in the garage, which stores the
	 * hospitals
	 */
	private HospitalBoard hospitalboard;

	/**
	 * Variable registering the location of the garage
	 */
	private final Location location;

	/**
	 * Variable registering the dispatchcenter of this garage
	 */
	private DispatchCenter dispatchcenter;

	/**
	 * Initialize this new garage with a given location and DispatchCenter
	 * 
	 * @param location
	 *            The location of this garage
	 * 
	 * @param dispatchcenter
	 *            The dispatchcenter of this garage
	 * 
	 * @post This new garage's DispatchCenter is set to the given DispatchCenter
	 * 
	 * @post This new garage's location is set to the given location
	 * 
	 * @post This new garage's HospitalBoard is initialized (but empty)
	 * 
	 * @post This new garage's list of units is initialized (but empty)
	 * 
	 * @throws IllegalArgumentException
	 *             , if the given location cannot be used
	 * 
	 * */
	public Garage(Location location, DispatchCenter dispatchcenter) {
		setUnits(new ArrayList<Unit>());
		setHospitalboard(new HospitalBoard());
		setDispatchcenter(dispatchcenter);

		if (canHaveAsLocation(location))
			this.location = location;
		else
			throw new IllegalArgumentException(
					"A Garage can't be created without a valid location");
	}

	/**
	 * Method for adding the given Unit to this Garage
	 * 
	 * @post	The given unit is added to this garage
	 * 
	 * @param 	u
	 *         	The Unit you want to add to this Garage
	 */
	public void addUnit(Unit u) {
		if (canHaveAsUnit(u)) {
			getUnits().add(u);
		}
	}

	/**
	 * Method for checking a DispatchCenter can be assigned to this Garage
	 * 
	 * @param dispatchCenter
	 *            The DispatchCenter you want to check for validity
	 * 
	 * @return Returns true if valid, false if not
	 */
	public boolean canHaveAsDispatchCenter(DispatchCenter dispatchCenter) {
		return (dispatchCenter != null);
	}

	/**
	 * Method for checking a Location can be assigned to this Garage
	 * 
	 * @param 	Location
	 *          The location you want to check for validity
	 * 
	 * @return 	Returns true if valid, false if not
	 */
	public boolean canHaveAsLocation(Location location) {
		return (location != null);
	}

	/**
	 * Method for checking if a Unit can be added to this Garage
	 * 
	 * @param 	Unit
	 *          The Unit you want to check for validity
	 * 
	 * @return 	Returns true if valid, false if not
	 */
	private boolean canHaveAsUnit(Unit u) {
		if(nameAlreadyOccurs(u.getName()))
			return false;
		return true;
	}

	/**
	 * Getter returning the available (= can be assigned) units that are located in this garage
	 * 
	 * @return 	Returns a list of units that are located in this garage
	 */
	public ArrayList<Unit> getAvailableUnits() {
		ArrayList<Unit> units = new ArrayList<Unit>();
		for (Unit u : getUnits()) {
			if (u.canBeAssigned()) {
				units.add(u);
			}
		}
		return units;
	}

	/**
	 * Getter fo rreturning the units of a given type that are available for assignment
	 * 
	 * @param 	type
	 *          the type the units have to be an instance of
	 * 
	 * @return 	Returns the list of units that are of the given type and available
	 */
	public ArrayList<Unit> getAvailableUnits(String type) {
		ArrayList<Unit> units = new ArrayList<Unit>();
		for (Unit u : getAvailableUnits()) {
			if (u.getClass().toString().equalsIgnoreCase("class unit." + type)) {
				units.add(u);
			}
		}
		return units;
	}

	/**
	 * Getter returning the dispatcherCenter where this garage is working for
	 * 
	 * @return 	Returns the dispatchCenter where this garage is working for
	 */
	public DispatchCenter getDispatchcenter() {
		return dispatchcenter;
	}

	/**
	 * Getter returning the hospitalBoard of this garage
	 * 
	 * @return 	Returns the hospitalBoard of this garage
	 */
	public HospitalBoard getHospitalboard() {
		return hospitalboard;
	}

	/**
	 * A method to get a list of all hospitals
	 * 
	 * @return 	Returns the list of hospitals
	 */
	public ArrayList<Hospital> getHospitals() {
		return getHospitalboard().getHospitalsClone();
	}

	/**
	 * A method to get a list of all hospitals, sorted on the closest to the
	 * given location
	 * 
	 * @param 	location
	 *          the location the hospitals returned have to be closest to
	 *          
	 * @return 	Returns list of hospitals, sorted closest to the given location
	 */
	public ArrayList<Hospital> getHospitals(Location location) {
		return getHospitalboard().getHospitals(location);
	}

	/**
	 * Getter returning the location of this garage
	 * 
	 * @return 	Returns the location of this garage
	 */
	public Location getLocation() {
		return location;
	}

	/**
	 * Getter returning a unit that is located in this garage with a given name
	 * 
	 * @param 	name
	 *          the name of the wanted unit
	 *          
	 * @return 	Returns the unit with the given name, null if the name doesn't occur
	 */
	public Unit getUnit(String name) {
		Unit unitToReturn = null;
		for (Unit u : units) {
			if (u.getName().equals(name)) {
				unitToReturn = u;
			}
		}
		return unitToReturn;
	}
	
	/**
	 * Getter returning the units that are assigned to his garage
	 * 
	 * @return Returns the list of units assigned to this garage
	 */
	private ArrayList<Unit> getUnits() {
		return units;
	}

	/**
	 * Getter returning the units that are assigned to his garage
	 * 
	 * @return Returns a cloned list of units assigned to this garage
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<Unit> getUnitsClone() {
		return (ArrayList<Unit>) units.clone();
	}


	/**
	 * Getter returning the units (cloned list) that are assigned to his garage
	 * 
	 * @return Returns the cloned list of units assigned to this garage
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<Unit> getUnitsCopy() {
		return (ArrayList<Unit>) units.clone();
	}

	/**
	 * Method for checking the given name already occurs in this garage
	 * 
	 * @param 	name
	 * 			The name you want to check that already exists in this garage
	 * 
	 * @return	Returns true if the name already occurs, false otherwise
	 */
	public boolean nameAlreadyOccurs(String name) {
		for (Unit u : getUnitsClone())
			if (u.getName().equals(name))
				return true;
		return false;
	}

	/**
	 * Sets the dispatchCenter where this garage is working for
	 * 
	 * @param 	dispatchcenter
	 *          the new dispatchCenter of this garage
	 *          
	 * @post 	the dispatchCenter of this garage is changed to the given
	 *       	dispatchCenter
	 * 
	 * @throws IllegalArgumentException
	 *             , if the given DispatchCenter is not valid
	 */
	public void setDispatchcenter(DispatchCenter dispatchcenter) {
		if (canHaveAsDispatchCenter(dispatchcenter))
			this.dispatchcenter = dispatchcenter;
		else
			throw new IllegalArgumentException(
					"A Garage can't be created without a valid dispatchcenter");
	}

	/**
	 * Sets the hospitalBoard of this garage to a given hospitalBoard
	 * 
	 * @param 	hospitalboard
	 *          the new hospitalBoard of this garage
	 *          
	 * @post 	the hospitalBoard of this garage is set to the given hospitalBoard
	 */
	public void setHospitalboard(HospitalBoard hospitalboard) {
		this.hospitalboard = hospitalboard;
	}

	/**
	 * Set the units assigned to this garage to a given list
	 * 
	 * @param 	units
	 *          the list of units that have to be assigned to this garage
	 *          
	 * @post 	the units of this garage is set to the given list of units
	 */
	public void setUnits(ArrayList<Unit> units) {
		this.units = units;
	}

}
